<template>
  <div class="image-uploader">
    <!-- 上传按钮 -->
    <div class="upload-button-container">
      <input
        type="file"
        :id="uploadId"
        :accept="accept"
        :multiple="multiple"
        @change="handleFileChange"
        class="file-input"
      />
      <label :for="uploadId" class="upload-button">
        {{ buttonText }}
      </label>
      <div class="upload-tip">{{ tipText }}</div>
    </div>

    <!-- 图片预览区域 -->
    <div v-if="previewImages.length > 0" class="preview-container">
      <div v-for="(img, index) in previewImages" :key="index" class="preview-item">
        <img :src="img" alt="预览图片" @click="handlePreview(img)" class="preview-img" />
        <div class="preview-actions">
          <el-button type="danger" size="small" @click="removeImage(index)">删除</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, defineProps, defineEmits } from 'vue';
import { ElMessage } from 'element-plus';

const props = defineProps({
  // 上传按钮文本
  buttonText: {
    type: String,
    default: '点击上传'
  },
  // 提示文本
  tipText: {
    type: String,
    default: '支持jpg、png格式，单个文件不超过5MB'
  },
  // 唯一ID，用于关联label和input
  uploadId: {
    type: String,
    default: 'file-upload'
  },
  // 是否支持多文件
  multiple: {
    type: Boolean,
    default: false
  },
  // 接受的文件类型
  accept: {
    type: String,
    default: 'image/jpeg,image/png,image/gif'
  },
  // 最大文件大小(MB)
  maxSize: {
    type: Number,
    default: 5
  }
});

// 当前预览的图片列表（base64格式）
const previewImages = ref([]);
// 实际的文件对象列表，用于最终提交
const files = ref([]);

const emit = defineEmits(['change', 'preview', 'remove']);

// 处理文件选择
const handleFileChange = (event) => {
  const selectedFiles = event.target.files;
  if (!selectedFiles || selectedFiles.length === 0) return;

  // 如果是单文件上传模式且已有图片，先清空
  if (!props.multiple && previewImages.value.length > 0) {
    previewImages.value = [];
    files.value = [];
  }

  // 处理选择的文件
  for (let i = 0; i < selectedFiles.length; i++) {
    const file = selectedFiles[i];
    
    // 验证文件大小
    if (file.size > props.maxSize * 1024 * 1024) {
      ElMessage.warning(`文件 ${file.name} 超过${props.maxSize}MB限制，已跳过`);
      continue;
    }
    
    // 创建FileReader来读取文件并生成预览
    const reader = new FileReader();
    reader.onload = (e) => {
      // 添加预览图片
      previewImages.value.push(e.target.result);
      // 添加文件到文件列表
      files.value.push(file);
      // 触发change事件
      emit('change', files.value);
    };
    reader.readAsDataURL(file);
  }
  
  // 重置input，使得用户可以重复选择同一文件
  event.target.value = '';
};

// 移除图片
const removeImage = (index) => {
  // 从预览和文件列表中移除
  previewImages.value.splice(index, 1);
  files.value.splice(index, 1);
  // 触发remove事件
  emit('remove', files.value);
};

// 预览图片
const handlePreview = (imageUrl) => {
  emit('preview', imageUrl);
};

// 导出方法和数据供父组件使用
defineExpose({
  previewImages,
  files,
  // 清空所有图片
  clearImages: () => {
    previewImages.value = [];
    files.value = [];
  },
  // 获取当前文件列表
  getFiles: () => files.value
});
</script>

<style scoped>
.image-uploader {
  margin-bottom: 16px;
}

.upload-button-container {
  margin-bottom: 10px;
}

.file-input {
  display: none;
}

.upload-button {
  display: inline-block;
  padding: 8px 16px;
  background-color: #409eff;
  color: white;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.upload-button:hover {
  background-color: #66b1ff;
}

.upload-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 5px;
}

.preview-container {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
}

.preview-item {
  position: relative;
  border: 1px solid #eee;
  border-radius: 4px;
  overflow: hidden;
}

.preview-img {
  width: 150px;
  height: 120px;
  object-fit: cover;
  display: block;
  cursor: pointer;
  transition: transform 0.3s;
}

.preview-img:hover {
  transform: scale(1.05);
}

.preview-actions {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  padding: 5px;
  text-align: center;
  opacity: 0;
  transition: opacity 0.3s;
}

.preview-item:hover .preview-actions {
  opacity: 1;
}
</style> 